[t:/]$ 지식_

java instance sizeof

2014/09/24

저는 자바 초보이며 C는 오래했지만 서민입니다. 따라서 다음 글은 초보의 학습 낙서이므로 뻘소리, 공상과학과 픽션이 포함됐을 가능성이 있음.

아파치 머하웃은 메모리를 아끼기 위해서 해시맵 등 대신 전용 기억부류를 제공한다. 그래? 그럼 얼맨큼? 미시적 분석을 위해 자바 인스턴스의 메모리 사용량을 뒤져보기로 한다.

자바에는 sizeof 연산자가 없다. 개별 인스턴스 메모리 사용량을 구하기 어렵다. 힙덤프, 코어덤프 분석은 일단 열외로 한다. 왜? 초보라서.

sizeof를 구현하려면 unsafe를 이용한 일종의 자바 해킹을 해야 한다. sun.misc.Unsafe 참조.

Unsafe 사용 예제를 찾았다.
https://www.jrebel.com/blog/java-memory-management

따라해보니 케바케로 잘 안 된다. 구글링 도중 찾은 이런저런 것들은 JVM 및 32/64/compressed 케바케가 반영되어 있지 않음. 나 또한 런타임 에러 쳐맞음.

결국 구세주를 찾았다 : ocean of memories
https://github.com/serkan-ozal/ocean-of-memories/blob/master/src/main/java/com/zeroturnaround/rebellabs/oceanofmemories/common/util/JvmUtil.java

자바 클래스 메모리 구조는 이렇다.
https://highlyscalable.wordpress.com/2012/02/02/direct-memory-access-in-java/

원래는 자바에서 다이렉트 메모리 접근을 위해 고안한듯. 나 같은 멤카피 줄이기 성애자들은 이런 글이 좋음.

가비지 컬렉션 참고 글
http://java-latte.blogspot.in/2013/08/garbage-collection-in-java.html

결과적으로, ocean of memories 를 통해 sizeof 를 돌린결과 (예쁜 코드는 나중에. 당근을 당근당근 빨리! 발코딩을 발코발코! 변수명 aaaa!!!!)

import com.zeroturnaround.rebellabs.oceanofmemories.common.util.JvmUtil;

public class addrtest {

      public static void main(String[] args) throws Exception {

          JvmUtil rrr = new JvmUtil();

          class MyStructure { int x; int y; }

          int qq[] = new int[8];

          MyStructure ee = new MyStructure();

          int a;
          Integer b = new Integer(100);

          a = 100;

          System.out.printf("eee = %d, %d\n", rrr.sizeOf(ee), rrr.sizeOf(qq));

          rrr.info();

//        while(true) {
//            Thread.sleep(1000);
//            System.out.print("!");
//        }
      }
}

와... int는 16바이트가 나옴. 왜? 메타가 12바이트임.

메타의 크기를 설명한 글을 보고 요약 하면

– 32bit jvm = 8 (_mark 4, _klass 4) – 64bit jvm = 16 – 64bit jvm + compressed = 12

즉 int가 16이 나온 이유는 메타 12 + int (4)임. 실제로 Integer.SIZE 찍으면 4나옴.

int [4] 의 크기는 ? = 메타 12 + 4*4 = 28임, 그런데 JVM은 8바이트 얼라인으로 끝선을 맞춤. 모포에 칼각 잡음. 그래서 32가 나옴.

JVM 얼라인 모양새 참고글
http://www.codeinstructions.com/2008/12/java-objects-memory-structure.html

클래스 배열을 쓰면 걍 포인터로 크기 잡힌다고 보면 됨. 대충.. 포인터 배열임. 그래서 클래스 배열은 걍 4바이트 짜리의 배열 + 메타의 크기가 됨.

ArrayList 등을 쓰면 양상이 바뀜. 이거 뭐야! 추적해보면 최초 3-4개 까지는 요상한 양상임. 이후에는 추가한 object의 크기만큼 증가함… slab 스타일로 미리 할당해 놓는듯? 똘똘이 스머프?

…인 듯 했으나 빌드할 때 마다 조금씩 바뀜.. -_-;; 추이는 있음.. 사전 할당, 캐쉬, 랜더마이즈(해킹 방지)와 관계있을지도… 잘 모르겠음..

결론 : 크리테오 데이터 분석 2등먹은 윈도 CE .NET 공역자이자 어울림 동기 이정윤 동생의 조언에 따르면 머하웃 버리고 VW에 올라타라고 함 (C/C++)





공유하기













[t:/] is not "technology - root". dawnsea, rss